package com.lwq.imserver.code;

import com.lwq.imserver.model.ChatRoom;
import com.lwq.imserver.model.system.SysUser;
import com.lwq.imserver.service.MessageService;
import com.lwq.imserver.util.RedisUtil;
import com.lwq.imserver.util.WebSocketUtil;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

/**
 * Description:
 * Author: LiuWenQing
 * Datetime: 2022/1/17 17:12
 */
@Configuration
@Component
@Slf4j
public class WebSocketServer {

    @Value("${netty.server.port}")
    private Integer port;

    @Autowired
    private MessageService messageService;
    @Autowired
    private RedisUtil redis;
    @Autowired
    private MongoTemplate mongoTemplate;

    private EventLoopGroup boss;
    private EventLoopGroup work;

    @PostConstruct()
    public void init() {
        new Thread(this::startServer).start();
    }

    private void startServer() {
        log.info("启动netty");
        //服务端需要2个线程组  boss处理客户端连接  work进行客服端连接之后的处理
        createWebEventGroup();
        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(boss, work)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG,3072)
                    .option(ChannelOption.SO_SNDBUF, 256*1024)
                    .option(ChannelOption.SO_RCVBUF,256*1024)
                    .childHandler(new WebSocketChannelInitializer(messageService,redis))
                    .childOption(ChannelOption.SO_KEEPALIVE, true);
            ChannelFuture channel = bootstrap.bind(port).sync();
            channel.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭资源
            boss.shutdownGracefully();
            work.shutdownGracefully();
        }
    }

    private void createWebEventGroup(){
        WebSocketUtil.userList = this.mongoTemplate.findAll(SysUser.class);
        WebSocketUtil.chatRoomList = this.mongoTemplate.findAll(ChatRoom.class);
        boss = new  NioEventLoopGroup();
        work = new NioEventLoopGroup();
    }

    public void destroy(EventLoopGroup bossGroup , EventLoopGroup workerGroup) {
        if(bossGroup != null && !bossGroup.isShuttingDown() && !bossGroup.isShutdown() ) {
            try {bossGroup.shutdownGracefully();}catch(Exception ignore) {}
        }

        if(workerGroup != null && !workerGroup.isShuttingDown() && !workerGroup.isShutdown() ) {
            try {workerGroup.shutdownGracefully();}catch(Exception ignore) {}
        }
    }
}
